package com.hs.jhzd.controller;

import com.google.common.base.Preconditions;
import com.hs.jhzd.entity.*;
import com.hs.jhzd.repository.*;
import com.hs.jhzd.utils.ToolUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;

@Controller
@RequestMapping("/shopping")
@Slf4j
public class ShoppingController {

    @Value("${jsbh}")
    private String jsbh;
    @Autowired
    private GoodsRepository goodsRepository;

    @Autowired
    private GoodsCategoryRepository goodsCategoryRepository;

    @Autowired
    private OrderGoodsRepository orderGoodsRepository;

    @Autowired
    private OrderRepository orderRepository;

    @Autowired
    private PrisonerAccountRepository prisonerAccountRepository;

    @Autowired
    private PrisonerAccountMoneyDetailReposity prisonerAccountMoneyDetailReposity;
    @Autowired
    private Jh_zjlzjlbRepository jh_zjlzjlbRepository;

    @RequestMapping("/categorys")
    @ResponseBody
    public List<GoodsCategory> categorys() {

        return goodsCategoryRepository.findByVisible("0");
    }

    @RequestMapping("/goods")
    @ResponseBody
    public List<Goods> goods(String categoryCode) {
        List<Goods> goods = goodsRepository.findByCategoryCodeAndVisible(categoryCode, "0");
        if (CollectionUtils.isEmpty(goods)) {
            return new ArrayList<>();
        }

        List<Goods> result = new ArrayList<>();
        goods.forEach(g -> {
            g.setPhoto(null);
            result.add(g);
        });

        return result;
    }

    @RequestMapping(value = {"/goods/photo"})
    @ResponseBody
    public byte[] goodsPhoto(HttpServletRequest request, HttpServletResponse response, String spbh) {
        response.setContentType(MediaType.IMAGE_JPEG_VALUE);

        Goods goods = goodsRepository.findByCode(spbh);
        return goods != null ? goods.getPhoto() : null;
    }

    @RequestMapping("/addOrder")
    @ResponseBody
    public boolean addOrder(@RequestBody OrderForm order) throws Exception {
        Preconditions.checkArgument(!CollectionUtils.isEmpty(order.getOrderGoods()),
                "order goods is null");
        String rybh = order.getRybh();
        PrisonerAccount prisonerAccount = findPrisonerAccount(rybh);
        Preconditions.checkArgument(prisonerAccount != null, "用户不存在  rybh = " + rybh);
        List<OrderGoods> validatedDtos = new ArrayList<>();
        double totalPrice = 0;
        double limitPrice = 0;
        String finalResultId = convert2Id12(new Date());
        for (OrderGoods dto : order.getOrderGoods()) {
            Goods goods = goodsRepository.findByCode(dto.getGoodsId());
            if (goods == null) {
                continue;
            }
            OrderGoods validatedDto = new OrderGoods();
            BeanUtils.copyProperties(dto, validatedDto);
            validatedDto.setZybh(convert2Id12(new Date()));
            validatedDto.setDdbh(finalResultId);
            validatedDto.setGoodsId(goods.getCode());
            validatedDto.setGoodsName(goods.getName());
            validatedDto.setQuantity(dto.getQuantity());
            validatedDto.setZj(validatedDto.getSubTotalPrice()+"");
            validatedDto.setJsbh(jsbh);
            validatedDto.setJsmc(jsbh);
            validatedDto.setScbj(0);

            validatedDto.setFinalQuantity(validatedDto.getQuantity());
            double subTotalPrice = validatedDto.getQuantity() * validatedDto.getUnitPrice();
            validatedDto.setSubTotalPrice(subTotalPrice);
            validatedDto.setState("0");
            if (!goods.isRestriction()) {
                limitPrice += subTotalPrice;
            }
            totalPrice += subTotalPrice;
            validatedDtos.add(validatedDto);
        }
        if (prisonerAccount.getAvailableBalance() == null) {
            prisonerAccount.setAvailableBalance(0.0);
        }
        if (prisonerAccount.getFrozenAssets() == null) {
            prisonerAccount.setFrozenAssets(0.0);
        }
        if (limitPrice > (prisonerAccount.getAvailableBalance() - prisonerAccount.getFrozenAssets())) {
            throw new Exception("在押人员" + prisonerAccount.getJsh() + ":" + prisonerAccount.getName()
                    + "下单失败！【可用余额】不足！可用余额余额：" + prisonerAccount.getAvailableBalance() + "，冻结金额："
                    + prisonerAccount.getFrozenAssets() + "，购物金额：" + totalPrice + "，限购金额：" + limitPrice);
        }
        order.setFinalPrice(order.getTotalPrice());
        order.setStatus("0");
        order.setJsmc(jsbh);
        order.setJsbh(jsbh);
        order.setId(finalResultId);
        updatefrozenAssets(prisonerAccount, limitPrice);
        List<OrderGoods> orderGoods = orderGoodsRepository.saveAll(validatedDtos);
        order.setOrderGoods(orderGoods);
        order.setScbj(0);
        orderRepository.save(order);

        String oldId = jh_zjlzjlbRepository.findZybh();
        Jh_zjlzjlb jh_zjlzjlb = new Jh_zjlzjlb();
        jh_zjlzjlb.setZYBH(ToolUtils.CreatePrimaryKey(oldId));
        jh_zjlzjlb.setDDBH(finalResultId);
        jh_zjlzjlb.setYE(prisonerAccount.getAvailableBalance() + "");
        jh_zjlzjlb.setRYBH(order.getRybh());
        jh_zjlzjlb.setCJSJ(new Date());
        jh_zjlzjlb.setXM(order.getPrisonerName());
        jh_zjlzjlb.setJSH(order.getJsh());
        jh_zjlzjlb.setJSBH(jsbh);
        jh_zjlzjlb.setJSMC(jsbh);
        jh_zjlzjlb.setLX("0");
        jh_zjlzjlbRepository.save(jh_zjlzjlb);
        log.debug("在押人员{}{}下单成功！购买物品：{}", prisonerAccount.getJsh(), prisonerAccount.getName(),
                order.toString());
        return true;

    }

    private void updateAvailableBalance(PrisonerAccount prisonerAccount, double limitPrice) {

        Double availableBalance = prisonerAccount.getAvailableBalance();// 本月额度
        Double frozenAssets = prisonerAccount.getFrozenAssets();
        if (prisonerAccount.getAvailableBalance() == null) {
            prisonerAccount.setAvailableBalance(0.0);
        }
        if (prisonerAccount.getFrozenAssets() == null) {
            prisonerAccount.setFrozenAssets(0.0);
        }
        log.debug("在押人员{}{}签收成功！原购物额度：{}，现购物额度{},原冻结金额{}，现冻结金额{}", prisonerAccount.getJsh(),
                prisonerAccount.getName(), availableBalance, (availableBalance - limitPrice), frozenAssets,
                (frozenAssets - limitPrice));

        availableBalance -= limitPrice;
        frozenAssets -= limitPrice;

        prisonerAccount.setAvailableBalance(availableBalance);
        prisonerAccount.setFrozenAssets(frozenAssets);
        prisonerAccountRepository.save(prisonerAccount);
    }

    private void updatefrozenAssets(PrisonerAccount prisonerAccount, double limitPrice) {

        Double frozenAssets = prisonerAccount.getFrozenAssets();
        if (prisonerAccount.getFrozenAssets() == null) {
            prisonerAccount.setFrozenAssets(0.0);
        }
        log.debug("在押人员{}{}下单成功！原冻结购物金额：{}，现冻结购物金额{}", prisonerAccount.getJsh(),
                prisonerAccount.getName(), frozenAssets, (frozenAssets + limitPrice));
        frozenAssets += limitPrice;
        prisonerAccount.setFrozenAssets(frozenAssets);
        prisonerAccountRepository.save(prisonerAccount);
    }

    @RequestMapping("/findOrderByRybh")
    @ResponseBody
    public List<OrderForm> findOrderByRybh(String rybh) {
        return orderRepository.findByRybhOrderByCreateTimeDesc(rybh);
    }

    @RequestMapping("/updateOrderStatus")
    @ResponseBody
    public boolean updateOrderStatus(String orderId, String status) {
        Optional<OrderForm> order = orderRepository.findById(orderId);
        if (!order.isPresent()) {
            throw new IllegalArgumentException("订单不存在");
        }
        order.get().setStatus(status);
        orderRepository.save(order.get());
        return true;
    }

    @RequestMapping("/updateOrderGoodsStatus")
    @ResponseBody
    public boolean updateOrderGoodsStatus(@RequestParam(required = true) String orderId,
                                          @RequestParam(required = true) String orderGoodsId,
                                          @RequestParam(required = true) String status, @RequestParam(required = true) String rybh) {
        Optional<OrderGoods> orderGoods = orderGoodsRepository.findById(orderGoodsId);

        if (!orderGoods.isPresent()) {
            throw new IllegalArgumentException("订单商品不存在");
        }
        orderGoods.get().setState(status);
        orderGoodsRepository.save(orderGoods.get());

        checkOrderStatus(orderId);
        PrisonerAccount prisonerAccount = prisonerAccountRepository.findByRybh(rybh);
        updateAvailableBalance(prisonerAccount, orderGoods.get().getSubFinalPrice());
        return true;
    }


    private void checkOrderStatus(String orderId) {
        log.debug("计算订单状态是否要修改，订单号{}", orderId);
        Optional<OrderForm> order = orderRepository.findById(orderId);
        if (!order.isPresent()) {
            return;
        }
        List<OrderGoods> goods = order.get().getOrderGoods();
        if (CollectionUtils.isEmpty(goods)) {
            return;
        }
        boolean ok = true;
        for (OrderGoods g : goods) {
            //状态(0:待审核，1:待发货，2:待签收，3:已签收，4:已删除)
            if (!StringUtils.equals(g.getState(), "3")) {
                log.debug("订单{}内商品{}状态为{}，不修改订单状态", orderId, g.getGoodsName(), g.getState());
                ok = false;
                break;
            }
        }
        if (ok) {
            log.debug("订单{}内所有商品已签收，现在去修改订单状态", orderId);
            order.get().setStatus("3");
            orderRepository.save(order.get());
        }
    }

    @RequestMapping("/findPrisonerAccount")
    @ResponseBody
    public PrisonerAccount findPrisonerAccount(String rybh) {
        return prisonerAccountRepository.findByRybh(rybh);
    }

    @RequestMapping("/findPrisonerAccountDetail")
    @ResponseBody
    public List<PrisonerAccountMoneyDetail> findPrisonerAccountDetail(String rybh) {
        return prisonerAccountMoneyDetailReposity.findByRybh(rybh);
    }

    /**
     * 按照日期+6位自增长整数组成id.
     *
     * @param date 时间
     * @return 作业编号
     */
    public static String convert2Id12(Date date) {
        if (date == null) {
            return null;
        }
        return DateFormatUtils.format(date, "yyMMddmmhhss")
                + String.format("%06x", nextInc.incrementAndGet() & 0x00FFFFFF);
    }

    private static AtomicInteger nextInc = new AtomicInteger((new java.util.Random()).nextInt());

}
